﻿@{
    ViewBag.Title = "HtmlSvg";
}

<div class="span12">
    <h2>HtmlSvg</h2>
    <hr />
    <div class="well">Kurzer Beschreibungstext für das aktuelle Formular</div>
</div>

<div class="span12">
    <div id="svgContainer" style="border: 1px solid #ccc; height: 400px; width: 920px;">
    </div>
</div>

<div class="span12">
    <div class="well">
        @Html.ActionLink("Zurück zur Startseite", "Index", "Home", null, new { @class = "btn btn-mini" })
    </div>
</div>

@section scripts
{
    <script>

        //var rap = new Raphael("svgContainer");
        //var circle = rap.circle(50, 40, 10);
        //circle.attr("fill", "#f00");


        //$('#svgContainer').on('click', '#testId', function (e) {
        //    //Im Link noch das aktuell ausgewählte Datum anhängen, damit dieses auch ausgewählt bleibt
        //    alert("Test");
        //});

        //Ein Zeiteintrag für das Diagramm
        function TimeEntry(startMinutes, endMinutes, diagramType) {
            this.startMinutes = startMinutes, //Die Startzeit in Minuten von 00:00
            this.endMinutes = endMinutes, //Die Endezeit in Minuten von 00:00
            this.type = diagramType; //Der Typ des Eintrags 'diagramTypes'
        }

        //Zeitdiagramm Contextvariablen zum Anpassen.
        function TimeDiagram() {
            this.raphael = new Raphael("svgContainer"),
            //Die unterschiedlichen Diagrammtypen mit den passenden Farben und Legendennamen
            this.diagramTypes = {
                Work: { value: 0, name: 'Arbeitszeit', gradStart: '#5BC0DE', gradEnd: '#339BB9' },
                Pause: { value: 10, name: 'Pause', gradStart: '#FBB450', gradEnd: '#F89406' },
                Holiday: { value: 20, name: 'Urlaub', gradStart: '#EE5F5B', gradEnd: '#C43C35' },
                Project: { value: 30, name: 'Projektzeit', gradStart: '#62C462', gradEnd: '#57A957' }
            },
            //Die Beschriftung der X-Achse
            this.times = ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00',
                          '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00',
                          '18:00', '19:00', '20:00', '21:00', '22:00', '23:00'],
            this.fontsize = 10, //Die Schriftgröße für die Beschriftung
            this.leftRightBorder = 20, //Der Abstand zum linken und rechten Rand des Diagramms
            this.topBottomBorder = 20, //Der Abstand zum oberen und unteren Rand des Diagramms
            this.diagramColor = '#ccc', //Farbe des Diagramms
            this.ctx = undefined, //Der Aktuelle Kontext, der dieser wird in DrawDiagramm gesetzt.
            this.canvWidth = undefined,
            this.canvHeight = undefined,
            this.diagramEntryHeight = 15, //Die Höhe der Zeiteinträge im Diagramm
            this.diagramEntryOffset = 3, //Der Abstand zwischen den Balken im Diagram
            this.diagramStartPosition = 10, //Die Startposition der Balkeneinträge im Diagramm
            this.LegendYPos = 10, //Die Y-Position unserer Legende (Achtung 0,0 liege Links Oben)
            this.LegendXPos = 10, //Die X-Position unserer Legende
            this.ctxAlpha = 0.75;  //Die globalen Alpha Einstellungen
        };

        //Funktion zum Zeichnen einer Linine
        TimeDiagram.prototype.drawLine = function (startX, startY, endX, endY) {
            var line = this.raphael.path("M" + startX + " " + startY + "L" + endX + " " + endY);
            //Damit die Linien auch nur ein Pixel breit sind muss das translate durchgeführt werden
            line.translate(0.5, 0.5);
            line.attr("stroke", this.diagramColor);
        };

        //Funktion zum Zeichnen eines Rechtecks
        TimeDiagram.prototype.drawRectangle = function (ctx, startX, startY, width, height, gradStart, gradEnd, borderColor, borderWidth) {
            //Zeichnen eines Diagrammeintrags/Rechtecks
            ctx.globalAlpha = this.ctxAlpha;
            ctx.beginPath();
            //Erst das Rechteck zeichnen
            ctx.rect(startX, startY, width, height);
            //Dann im Rechteck den passenden Lineargradienten für die Farben einfügen
            var grd = ctx.createLinearGradient(startX, startY, startX, startY + height);
            grd.addColorStop(0, gradStart);
            grd.addColorStop(1, gradEnd);
            this.ctx.fillStyle = grd;
            this.ctx.fill();

            //Prüfen ob die Parameter auch der Funktion übergeben wurden.
            if (borderColor !== undefined && borderWidth !== undefined) {
                ctx.lineWidth = borderWidth;
                ctx.strokeStyle = borderColor;
                ctx.stroke();
            }
        };

        //Funktion zum Erstellen des Diagramms
        TimeDiagram.prototype.drawDiagram = function () {
            //Achtung wir müssen hier die Reihenfolge einhalten, das auch alle Variablen Initialisiert sind.
            //Erst in der drawDiagram Funktion wird der Context und das Canvas geladen.
            //this.canvas = document.getElementById(canvasId); //Das Canvas Element heraussuchen
            //this.ctx = this.canvas.getContext('2d'), //Den aktuellen Kontext ermitteln
            //this.canvWidth = this.canvas.width, //Die Breite unseres Canvas bestimmen
            //this.canvHeight = this.canvas.height; //Die Höhe unseres Canvas bestimmen
            this.canvWidth = 920,
            this.canvHeight = 400;
            this.raphael.renderfix();
            var count = 0,
                //Den abstand zwischen den Elementen anhand der Breite des Canvas bestimmen und ACHTUNG das hier die Border ebenfalls mit abgezogen wird.
                abstand = (this.canvWidth - 2 * this.leftRightBorder) / (this.times.length),
                quarter = Math.round(abstand / 4), //Den Abstand für eine Viertelstunde berechnen
                textPos = this.canvHeight - (this.topBottomBorder / 2) + 3; //Die Textposition für die Uhrzeit bestimmen

            //this.ctx.font = 'normal ' + this.fontsize + 'px Calibri';
            //this.ctx.strokeStyle = this.diagramColor;
            //this.ctx.lineWidth = 1;

            //Die X-Achse zeichnen
            this.drawLine(this.leftRightBorder - 5, this.canvHeight - this.topBottomBorder, this.canvWidth - this.leftRightBorder, this.canvHeight - this.topBottomBorder);
            var counter = 0;
            //Y-Achsen erstellen Achtung hier muss bei den "i" Werten x-Position darauf geachtet werden das 0.5 dazu addiert wird damit das Antializing "deaktiviert" wird.
            for (var i = this.leftRightBorder; counter++ < this.times.length; i = i + abstand) {
                //Der wert für i wird zwar gerundet, sollte aber nicht direkt auf i passieren, damit der Wert nicht bei jedem Durchgang weiter verändert wird.
                var yPos = Math.round(i);
                //Stundenlinien erstellen
                this.drawLine(this.ctx, yPos, this.canvHeight - this.topBottomBorder + 5, yPos, this.topBottomBorder),
                //Erstellen der Virtelstundenanzeigen
                this.drawLine(yPos + quarter, this.canvHeight - this.topBottomBorder + 3, yPos + quarter, this.canvHeight - this.topBottomBorder - 3),
                this.drawLine(yPos + 2 * quarter, this.canvHeight - this.topBottomBorder + 5, yPos + 2 * quarter, this.canvHeight - this.topBottomBorder - 5),
                this.drawLine(yPos + 3 * quarter, this.canvHeight - this.topBottomBorder + 3, yPos + 3 * quarter, this.canvHeight - this.topBottomBorder - 3);
                //Uhrzeit anzeigen unterhalb der X-Achse
                this.raphael.text(yPos + 18, textPos, this.times[count++]);
            }
        };

        //Funktion zum Erstellen der Zeitblöcke
        TimeDiagram.prototype.drawTimeEntries = function (timeEntries) {
            var yPosByType = [],
                //Die YPostion für den übergebenen Typen ermitteln, wenn diese noch nicht vorhanden ist
                //wird der Typ der Listehinzugefügt.
                addYposType = function (type, index) {
                    var diagramIdx = index;
                    for (var i = 0; i < yPosByType.length; i++) {
                        //Wenn der Typ gefunden wurde, dann die passende Position zurückgegeben.
                        if (yPosByType[i].typ === type) {
                            return yPosByType[i].pos;
                        }
                    }

                    var newPos = (yPosByType.length * (diagramIdx.diagramEntryHeight + diagramIdx.diagramEntryOffset));
                    //Der Typ ist noch nicht enthalten, also muss er hinzugefügt werden
                    yPosByType.push({ typ: type, pos: newPos });
                    return newPos;
                };

            //Für jeden Eintrag das passende "viereck" zeichnen
            for (var i = 0; i < timeEntries.length; i++) {
                //Berechnen bei welchem Pixel das Zeichnen beginnen soll dafür werden die Minuten für einen Tag 1440 als 100% Maß genommen. 
                //ACHTUNG hier muss die Border von der Gesamtbreite abgezogen werden
                var startPix = Math.round(((this.canvWidth - 2 * this.leftRightBorder) * timeEntries[i].startMinutes / 1440) + this.leftRightBorder) + 0.5,
                    //Beim Ende eines Eintrags, berechnen wir als erstes die Gesamtlänge vom Start des Diagramms, hier muss dann die Startzeit abgezogen werden um das tatsächliche Ende zu erhalten.
                    endPix = Math.round(((this.canvWidth - 2 * this.leftRightBorder) * (timeEntries[i].endMinutes - timeEntries[i].startMinutes) / 1440)) + 0.5,
                    //Die yPos wir anhand der X-Achse bestimmt und da wir von Links oben "zählen" mit 0,0 müssen hier die Werte entsprechend berechnet werden.
                    //Außerdem muss die Position je nach dem welcher entryType angezeigt werden soll um Y Pixel verschoben werden, mit 'addYposType'
                    yPos = (this.canvHeight - this.topBottomBorder - this.diagramStartPosition - this.diagramEntryHeight - addYposType(timeEntries[i].type, this)) + 0.5;

                //Erstellen Des Arbeitszeit eintrags mit den passenden Position und Farbe
                this.drawRectangle(this.ctx, startPix, yPos, endPix, this.diagramEntryHeight,
                    timeEntries[i].type.gradStart, timeEntries[i].type.gradEnd);
            }
        };

        //Erstellen einer Legende für unser Diagramm
        TimeDiagram.prototype.drawLegend = function (timeEntries) {
            //Prüfen ob der Typ der übergeben wurde in unserer Zeitliste der Einträge die angezeigt werden enthalten ist.
            var checkTimeEntriesForType = function (typeToCheck) {
                for (var i = 0; i < timeEntries.length; i++) {
                    //Nur wenn der Typ gefunden wurde, dann wird dieser auch angezeigt.
                    if (timeEntries[i].type === typeToCheck) {
                        return true;
                    }
                }
                return false;
            },
                //Zählt wie viele unterschiedliche timeEntries/diagramTypes in der übergebenen Liste enthalten sind.
                countTimeEntryTypes = function () {
                    var anz = [];
                    for (var i = 0; i < timeEntries.length; i++) {
                        //Prüfen ob der Typ schon in unserer Liste enthalten ist.
                        if (anz.indexOf(timeEntries[i].type) === -1) {
                            anz.push(timeEntries[i].type);
                        }
                    }
                    //Die anzahl der Listeneinträge zurückgegeben
                    return anz.length;
                };

            //Die Umrahmung und den Hintergrund für unsere Legende festlegen
            this.drawRectangle(this.ctx, this.LegendXPos - 2.5, this.LegendYPos - 2.5, 125, countTimeEntryTypes() * 15, '#F5F5F5', '#F5F5F5', '#ccc', 1);
            //Die yPos setzten, da diese verändert wird darf nicht this.LegendYPos verwendet werden.
            var yPos = this.LegendYPos;

            //Alle Properties unserer Diagrammtypen durchgehen und mit den Werten in den Zeiteinträgen vergleichen, damit wir wissen welche auch im Diagramm angezeigt werden.
            for (var prop in this.diagramTypes) {
                //Wenn es sich um ein Property handelt, welches zu unserem Diagrammtyp gehört, prüfen ob dies ebenfalls in timeEntries enthalten ist.
                if (this.diagramTypes.hasOwnProperty(prop) && checkTimeEntriesForType(this.diagramTypes[prop])) {
                    //Die Farbe unseres Eintrags an der richtigen Stelle erstellen
                    this.drawRectangle(this.ctx, this.LegendXPos, yPos, 10, 10,
                        this.diagramTypes[prop].gradStart, this.diagramTypes[prop].gradEnd);

                    this.ctx.fillStyle = 'black';
                    //Den Namen unseres Eintrags neben die Farbe schreiben
                    this.ctx.fillText(this.diagramTypes[prop].name, this.LegendXPos + 15, yPos + 9);

                    //Die nächste Position berechnen für den nächsten Eintrag.
                    yPos = yPos + 15;
                }
            }
        };

        var diagram = new TimeDiagram();
        //Das Diagramm zeichnen
        diagram.drawDiagram();

        var entries = [new TimeEntry(45, 240, diagram.diagramTypes.Work), new TimeEntry(120, 600, diagram.diagramTypes.Project),
                       new TimeEntry(820, 960, diagram.diagramTypes.Project), new TimeEntry(320, 1140, diagram.diagramTypes.Work),
                       new TimeEntry(520, 1200, diagram.diagramTypes.Holiday), new TimeEntry(60, 140, diagram.diagramTypes.Pause)];
        //Die Zeiteinträge zeichnen.
        //diagram.drawTimeEntries(entries);
        //Erstellen der Legende
        //diagram.drawLegend(entries);




    </script>

}
